package org.tamal.persistence;

import java.math.BigDecimal;
import java.util.Date;
import java.util.Set;

import javax.persistence.Cacheable;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.Version;

import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.annotations.DynamicUpdate;

/**
 * This class represents Account.
 * @author Tamal Kanti Nath
 */
@Entity
@Cacheable
@DynamicUpdate
@Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL)
public class Account {

    private Long id;
    private Branch branch;
    private BigDecimal amount;
    private Set<Customer> customers;
    private Date lastUpdate;

    /**
     * Returns the id.
     * @return the id
     */
    @Id
    @GeneratedValue
    public Long getId() {
        return id;
    }

    /**
     * Sets the id.
     * @param id the id to set
     */
    public void setId(Long id) {
        this.id = id;
    }

    /**
     * Returns the branch.
     * @return the branch
     */
    @ManyToOne(optional = false, cascade = CascadeType.ALL)
    public Branch getBranch() {
        return branch;
    }

    /**
     * Sets the branch.
     * @param branch the branch to set
     */
    public void setBranch(Branch branch) {
        this.branch = branch;
    }

    /**
     * Returns the amount.
     * @return the amount
     */
    @Column(nullable = false)
    public BigDecimal getAmount() {
        return amount;
    }

    /**
     * Sets the amount.
     * @param amount the amount to set
     */
    public void setAmount(BigDecimal amount) {
        this.amount = amount;
    }

    /**
     * Returns the customers.
     * @return the customers
     */
    @ManyToMany(cascade = CascadeType.ALL)
    public Set<Customer> getCustomers() {
        return customers;
    }

    /**
     * Sets the customers.
     * @param customers the customers to set
     */
    public void setCustomers(Set<Customer> customers) {
        this.customers = customers;
    }

    /**
     * Returns the lastUpdate. Used for optimistic locking.
     * @return the lastUpdate
     */
    @Version
    public Date getLastUpdate() {
        return lastUpdate;
    }

    /**
     * Sets the lastUpdate.
     * @param lastUpdate the lastUpdate to set
     */
    public void setLastUpdate(Date lastUpdate) {
        this.lastUpdate = lastUpdate;
    }

    /**
     * Indicates whether the specified object equals to this object.<br/>
     * For Account entity, the ID is the only business key. Two branches are
     * considered equal if their name are equal.
     *
     * @param obj the reference object with which to compare
     * @return if this Account is the same as the obj argument; false otherwise
     */
    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (!(obj instanceof Account)) {
            return false;
        }
        Account a = (Account) obj;
        if (id == null) {
            if (a.id == null) {
                return true;
            }
            return false;
        }
        return id.equals(a.id);
    }

    /**
     * The hash code is generated from name.
     * @return hash code value for branch
     */
    @Override
    public int hashCode() {
        return id == null ? 0 : id.hashCode();
    }

    @Override
    public String toString() {
        return "Id: " + id + " amount: " + amount;
    }
}
